package com.heima.leetcode.practice;

/**
 * @author 勾新杰
 * @version 1.0
 * @description: leetcode 189. 轮转数组
 * @date 2025/9/30 11:35
 */
public class E189 {

    /**
     * 方法一：递归的思想，但是扫描序列可能覆盖不了全数组
     * 缺点：有的地方可能会永远访问不到
     *
     * @param nums 数组
     * @param k    旋转的位数
     */
    public void rotate1(int[] nums, int k) {
        int index = 0;
        do {
            index = (index + k) % nums.length;
            swap(nums, 0, index);
        } while (index != 0);
    }

    /**
     * 交换数组两个索引位置的元素
     *
     * @param nums   数组
     * @param index1 索引1
     * @param index2 索引2
     */
    private void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }

    /**
     * 方法二：创建一个新数组，将原数组的元素复制到新数组中，在新数组中，将元素移动k个位置
     * 缺点：创建了额外的数组
     *
     * @param nums 源数组
     * @param k    旋转的位数
     */
    public void rotate2(int[] nums, int k) {
        int[] newArray = new int[nums.length];
        for (int i = 0; i < nums.length; i++) {
            newArray[(i + k) % nums.length] = nums[i];
        }
        System.arraycopy(newArray, 0, nums, 0, nums.length);
    }

    /**
     * 方法三：将数组进行三次翻转，实际上就是将数组看成两部分，一次整体翻转，两次局部翻转
     * 缺点：三次翻转
     *
     * @param nums 源数组
     * @param k    旋转的位数
     */
    public void rotate3(int[] nums, int k) {
        k %= nums.length;
        reverse(nums, 0, nums.length - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, nums.length - 1);
    }

    /**
     * 翻转数组
     *
     * @param nums 数组
     * @param start 开始索引
     * @param end 结束索引
     */
    private void reverse(int[] nums, int start, int end){
        while(start < end){
            swap(nums, start, end);
            start++;
            end--;
        }
    }
}
